package librairies.dictionnaire.dico;

import librairies.arborescence.arbre.BinarbreAVL;
import librairies.arborescence.interfaces.IBinarbre;
import librairies.dictionnaire.interfaces.IDictionnaire;
import librairies.dictionnaire.interfaces.IDonneeDico;
import librairies.liste.interfaces.IListe;
import librairies.liste.list.ListeDC;
import librairies.liste.list.ListeDCE;

/**
 * dictionnaire dans un arbre binaire.
 * 
 * @author mlozach
 * @param <E> type de l'elements dans le dico
 */
public class DicoBinarbre<E extends IDonneeDico<E>> implements IDictionnaire<E>
{
	private IBinarbre<E> binarbre;
	
	/**
	 * constructeur par default.
	 */
	public DicoBinarbre() 
	{
		this.binarbre = null;
	}
	
	/**
	 * constructeur par recopie.
	 * @param file la liste d'entree
	 */
	public DicoBinarbre(IListe<E> file)
	{
		this();
		this.addWords(file);
	} 
	
	@Override
	public IDictionnaire<E> addWords(IListe<E> words) 
	{
		ListeDCE<E> tmp = new ListeDCE<E>();
		
		for(int i = 0; i < words.size(); ++i)
		{
			tmp.add(words.get(i));
		}
		
		if(this.binarbre == null)
		{
			this.binarbre = new BinarbreAVL<E>(words.get(0));
		}
		
		this.binarbre = this.binarbre.addAll(tmp);
		
		return this;
	}

	@Override
	public IDictionnaire<E> cutWords(IListe<E> words) 
	{
		if(this.binarbre == null || this.size() == 0)
		{
			return this;
		}
		
		ListeDCE<E> tmp = new ListeDCE<E>();
			
		for(int i = 0; i < words.size(); ++i)
		{
			tmp.add(words.get(i));
		}
		
		this.binarbre = this.binarbre.cutAll(tmp);
	
		return this;
	}

	@Override
	public int size() 
	{
		if(this.binarbre == null)
		{
			return 0;
		}
		
		IListe<E> tmp = new ListeDC<E>();
		
		tmp = this.binarbre.infixe();
		
		return tmp.size();
	}
	
	@Override
	public boolean exists(E word) 
	{
		if(this.binarbre == null || this.size() == 0)
		{
			return false;
		}
		
		if(this.binarbre.containsVal(word))
		{
			return true;
		}
		
		return false;
	}
	
	@Override
	public IListe<E> commonPrefix(E prefix) 
	{
		IListe<E> tmp = new ListeDCE<E>();	
		
		if(prefix == null)
		{
			return tmp;
		}
		
		String lePrefix = prefix.getValue();
		
		if(lePrefix == null || lePrefix.length() == 0)
		{
			return tmp;
		}
		
		if(this.binarbre.isLeaf())
		{
			if(this.binarbre.getVal().contains(lePrefix))
			{
				tmp.add(this.binarbre.getVal());
				return tmp;
			}
		}
		else
		{
			tmp.addAll(this.binarbre.getLeft().prefixe());
			tmp.addAll(this.binarbre.getRight().prefixe());
		}

		//TODO a voir plus tard
		
		return tmp;
	}

	@Override
	public E getObjet(String word)
	{
		//TODO a voir plus tard
		return null;
	}
	
	@Override
	public IListe<E> contains(E prefix) 
	{
		//TODO a voir plus tard
		return null;
	}
	
	public IBinarbre<E> getBinarbre() {return binarbre;}

	/**
	 * methode object.
	 */
	public String toString() 
	{
		String res = "";
		
		if(this.binarbre!=null) 
		{
			IListe<E> liste = this.binarbre.infixe();
			for(int i = 0; i < liste.size(); i++) res += liste.get(i) + "\n";
		}
		
		return res;
	}
}